package io.kimmking.rpcfx.demo.provider;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.kimmking.rpcfx.demo.api.*;
//import io.kimmking.rpcfx.server.RpcfxInvoker;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.UnknownHostException;

@SpringBootApplication
@RestController
public class RpcfxServerApplication implements ApplicationContextAware { // 相当于spring的后门

    private ApplicationContext applicationContext;

	public static void main(String[] args) throws Exception {

//		// start zk client
//		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
//		CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181").namespace("rpcfx").retryPolicy(retryPolicy).build();
//		client.start();
//
//
//		// register service
//		// xxx "io.kimmking.rpcfx.demo.api.UserService"
//
//		String userService = "io.kimking.rpcfx.demo.api.UserService";
//		registerService(client, userService);
//		String orderService = "io.kimking.rpcfx.demo.api.OrderService";
//		registerService(client, orderService);


		// 进一步的优化，是在spring加载完成后，从里面拿到特定注解的bean，自动注册到zk

		SpringApplication.run(RpcfxServerApplication.class, args);
	}

//	private static void registerService(CuratorFramework client, String service) throws Exception {
//		ServiceProviderDesc userServiceSesc = ServiceProviderDesc.builder()
//				.host(InetAddress.getLocalHost().getHostAddress())
//				.port(8080).serviceClass(service).build();
//		// String userServiceSescJson = JSON.toJSONString(userServiceSesc);
//
//		try {
//			if ( null == client.checkExists().forPath("/" + service)) {
//				client.create().withMode(CreateMode.PERSISTENT).forPath("/" + service, "service".getBytes());
//			}
//		} catch (Exception ex) {
//			ex.printStackTrace();
//		}
//
//		client.create().withMode(CreateMode.EPHEMERAL).
//				forPath( "/" + service + "/" + userServiceSesc.getHost() + "_" + userServiceSesc.getPort(), "provider".getBytes());
//	}

//	@Autowired
//	RpcfxInvoker invoker;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext){
	    this. applicationContext = applicationContext;
    }

	@PostMapping("/")
	public RpcfxResponse call(@RequestBody RpcfxRequest request) {
        String serviceClass = request.getServiceClass();
//        Class kclass = Class.forName(serviceClass);
//        UserService service = (UserService)this.applicationContext.getBean(kclass);

        //作业1：给成泛型和反射
        UserService service = (UserService)this.applicationContext.getBean(serviceClass);
        Class[] classes = new Class[request.getParams().length];
        for(int i = 0; i < classes.length; i++){
            classes[i] = request.getParams()[i].getClass();
        }
        RpcfxResponse response = new RpcfxResponse();
        try {
            Method method  = UserService.class.getMethod(request.getMethod(), classes);  // 封装类型
            Object result = method.invoke(service, request.getParams());
            //两次json序列化能否合并成一次
            response.setResult(JSON.toJSONString(result, SerializerFeature.WriteClassName)); //result 对象类型，fastJson可以反序列化
            response.setStatus(true);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            //2,Xstream 或二进制hession等
            //3 封装一个统一的RpcFxException （客户端也需要判断）
            e.printStackTrace();
            response.setException(e);
            response.setStatus(false);
        }
        System.out.println(response);
        return response;
    }

//	@Bean
//	public RpcfxInvoker createInvoker(@Autowired RpcfxResolver resolver){
//		return new RpcfxInvoker(resolver);
//	}
//
//	@Bean
//	public RpcfxResolver createResolver(){
//		return new DemoResolver();
//	}

	// 能否去掉name
	//

	// annotation


	@Bean(name = "io.kimmking.rpcfx.demo.api.UserService")
	public UserService createUserService(){
		return new UserServiceImpl();
	}

	@Bean(name = "io.kimmking.rpcfx.demo.api.OrderService")
	public OrderService createOrderService(){
		return new OrderServiceImpl();
	}

}
